
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

package com.hlkj.pay.app.common.impl;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.provider.Aes256EncryptionProvider;
import com.hlkj.framework.common.util.date.LocalDateTimeUtils;
import com.hlkj.framework.extension.executor.ExtensionExecutor;
import com.hlkj.framework.extension.scenario.BizScenario;
import com.hlkj.pay.app.common.MessageExtPt;
import com.hlkj.pay.app.common.ext.ChannelSendDTO;
import com.hlkj.pay.common.CommonResultCode;
import com.hlkj.pay.config.SmsTemplateProperties;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.dto.common.SmsConfig;
import com.hlkj.pay.infrastructure.model.common.MessageRecordDO;
import com.hlkj.pay.infrastructure.model.common.TemplateDO;
import com.hlkj.pay.service.common.IMessageRecordService;
import com.hlkj.pay.service.common.IPlatFormConfigService;
import com.hlkj.pay.util.TemplateVariableUtils;
import com.hlkj.pay.vo.common.req.EmailSendReq;
import com.hlkj.pay.vo.common.req.MessageSendParamsReq;
import com.hlkj.pay.vo.common.req.SmsSendReq;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.UUID;

/**
 * @author monk@techsun.com
 * @date 2023/04/25 14:31
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MessageSendCommonService {
    private final ExtensionExecutor extensionExecutor;
    private final IMessageRecordService messageRecordService;
    private final IPlatFormConfigService platFormConfigService;
    private final Aes256EncryptionProvider aes256EncryptionProvider;

    private final MessageConsumerSelector messageConsumerSelector;
    private final SmsTemplateProperties smsTemplateProperties;

    @Value("${communication.request_log:false}")
    private boolean requestLog;
    /**
     * sendSms
     *
     * @param templateDO
     * @param smsSendReq
     * @return
     */
    public CommonResult<String> sendSms(TemplateDO templateDO, SmsSendReq smsSendReq) {
        messageConsumerSelector.phoneConsumerSelect(smsSendReq);
        if (!StringUtils.hasText(smsSendReq.getPhone())) {
            return CommonResult.error(CommonResultCode.MESSAGE_RECEIVER_DOES_NOT_EXIST);
        }
        Long sendTime = smsSendReq.getSendTime();
        MessageRecordDO messageRecordDO = messageRecordDO(templateDO, sendTime, smsSendReq);
        messageRecordDO.setReceiver(smsSendReq.getPhone());
        // messageRecordDO.setConsumerCode(smsSendReq.getConsumerCode());
        messageSendProcess(messageRecordDO, templateDO, smsSendReq);
        try {
            messageRecordService.addMessageRecord(messageRecordDO);
        }catch (Exception e){
            log.error("message error:{}",e,e.getMessage(),e);
        }
        return CommonResult.success(messageRecordDO.getMessageId());
    }

    /**
     * sendEmail
     *
     * @param templateDO
     * @param emailSendReq
     * @return
     */
    public CommonResult<String> sendEmail(TemplateDO templateDO, EmailSendReq emailSendReq) {
        messageConsumerSelector.emailConsumerSelect(emailSendReq);
        if (!StringUtils.hasText(emailSendReq.getEmail())) {
            return CommonResult.error(CommonResultCode.MESSAGE_RECEIVER_DOES_NOT_EXIST);
        }
        Long sendTime = emailSendReq.getSendTime();
        MessageRecordDO messageRecordDO = messageRecordDO(templateDO, sendTime, emailSendReq);
        messageRecordDO.setReceiver(emailSendReq.getEmail());
        // messageRecordDO.setConsumerCode(emailSendReq.getConsumerCode());
        messageSendProcess(messageRecordDO, templateDO,emailSendReq);
        messageRecordService.addMessageRecord(messageRecordDO);
        return CommonResult.success(messageRecordDO.getMessageId());
    }

    /**
     * 同步调用 or message 异步处理
     *
     * @param messageRecordDO
     * @param templateDO
     */
    void messageSendProcess(MessageRecordDO messageRecordDO, TemplateDO templateDO,MessageSendParamsReq messageSendParamsReq) {
        if (!CommonEnum.SEND_TIME_TYPE.IMMEDIATELY.getCode().equals(messageRecordDO.getSendTimeType())) {
            return;
        }
        SmsConfig smsConfig = platFormConfigService.getSmsConfig();
        ChannelSendDTO channelSendDTO=new ChannelSendDTO();
        channelSendDTO.setMessageRequestId(messageRecordDO.getMessageId());
        channelSendDTO.setTestSendMessage(smsTemplateProperties.isTestSendMessage());
		try {
			channelSendDTO.setReceiver(aes256EncryptionProvider.decrypt(messageRecordDO.getReceiver()));
		}
		catch (Exception e) {
			throw new RuntimeException(e);
		}
		// channelSendDTO.setSender();
        channelSendDTO.setParams(messageRecordDO.getTemplateParameter());
        channelSendDTO.setTemplateDO(templateDO);
        channelSendDTO.setSmsConfig(smsConfig);
        // channelSendDTO.setContent();
        // channelSendDTO.setSubject();
        CommonEnum.TEMPLATE_TYPE templateType = CommonEnum.TEMPLATE_TYPE.from(templateDO.getTemplateType());
        switch (templateType) {
            case EMAIL:
                break;
            case DOMESTIC_SMS:
            case INTERNATIONAL_SMS:
                String result = extensionExecutor.execute(MessageExtPt.class,
                        BizScenario.valueOf(smsConfig.getType()), ex -> ex.sendMessage(channelSendDTO));
                try {
                    if (!StringUtils.isEmpty(result)) {
                        messageRecordDO.setStatus(CommonEnum.STATUS.SUBMIT_FAIL.getCode());
                        messageRecordDO.setRemark(result);
                    }
                    else {
                        messageRecordDO.setStatus(CommonEnum.STATUS.SUBMIT_SUCCESS.getCode());
                        messageRecordDO.setRemark(result);
                    }
                }
                
                catch (Exception e) {
                    messageRecordDO.setStatus(CommonEnum.STATUS.SUBMIT_FAIL.getCode());
                    messageRecordDO.setRemark(e.getMessage());
                }
                break;
            default:
        }
    }

    /**
     * base MessageRecord
     *
     * @param templateDO
     * @param messageSendParamsReq
     * @param sendTime
     * @return
     */
    MessageRecordDO messageRecordDO(TemplateDO templateDO,  Long sendTime,
            MessageSendParamsReq messageSendParamsReq) {
        MessageRecordDO messageRecordDO = new MessageRecordDO();
        messageRecordDO.setMessageId(UUID.randomUUID().toString());
        messageRecordDO.setTemplateType(templateDO.getTemplateType());
        messageRecordDO.setTemplateCode(templateDO.getTemplateCode());
        if (sendTime == null) {
            messageRecordDO.setSendTimeType(CommonEnum.SEND_TIME_TYPE.IMMEDIATELY.getCode());
            messageRecordDO.setStatus(CommonEnum.STATUS.SUBMITING.getCode());
            messageRecordDO.setSendTime(LocalDateTimeUtils.datatimeToTimestamp(LocalDateTime.now()));
        }
        else {
            messageRecordDO.setSendTime(sendTime);
            messageRecordDO.setSendTimeType(CommonEnum.SEND_TIME_TYPE.TIMING.getCode());
            messageRecordDO.setStatus(CommonEnum.STATUS.WAIT_SUBMIT.getCode());
        }
        if (messageSendParamsReq != null) {
            messageRecordDO.setTemplateParameter(TemplateVariableUtils.sequenceMessageData(messageSendParamsReq));
        }
        messageRecordDO.setContent(TemplateVariableUtils.messageText(templateDO.getContent(),messageRecordDO.getTemplateParameter()));
        return messageRecordDO;
    }


    

}
